package com.life.ai.server.modules.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.life.ai.server.common.constants.UserConstants;
import com.life.ai.server.common.domain.PageQuery;
import com.life.ai.server.common.exception.ServiceException;
import com.life.ai.server.common.utils.AssertUtils;
import com.life.ai.server.modules.system.entity.SysRole;
import com.life.ai.server.modules.system.entity.SysRoleMenu;
import com.life.ai.server.modules.system.enums.RoleStatusEnum;
import com.life.ai.server.modules.system.mapper.SysRoleMapper;
import com.life.ai.server.modules.system.model.vo.SysRoleVO;
import com.life.ai.server.modules.system.service.SysRoleMenuService;
import com.life.ai.server.modules.system.service.SysRoleService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 角色信息表 服务实现类
 * </p>
 *
 * @author kylewka
 * @since 2024-06-11
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Resource
    private SysRoleMenuService roleMenuService;

    /**
     * 构建分页和列表的通用查询条件
     *
     * @param role 角色信息
     * @return queryWrapper
     */
    private QueryWrapper<SysRole> queryWrapper(SysRole role) {
        QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
        // 构建查询条件
        queryWrapper.lambda().like(StrUtil.isNotBlank(role.getName()), SysRole::getName, role.getName())
                .eq(ObjectUtil.isNotNull(role.getCode()), SysRole::getCode, role.getCode())
                .eq(StrUtil.isNotBlank(role.getStatus()), SysRole::getStatus, role.getStatus());
        return queryWrapper;
    }

    /**
     * 查询系统角色分页
     *
     * @param page 分页信息
     * @param role 角色信息
     * @return 角色分页
     */
    @Override
    public Page<SysRole> selectRolePage(PageQuery page, SysRole role) {
        return page(page.build(), queryWrapper(role));
    }

    /**
     * 查询系统角色列表
     *
     * @param role 角色信息
     * @return 角色列表
     */
    @Override
    public List<SysRole> selectRoleList(SysRole role) {
        return list(queryWrapper(role));
    }

    /**
     * 根据角色ID查询信息
     *
     * @param roleId 角色ID
     * @return 角色信息
     */
    //@RedisCache(name = SystemCacheConstant.ROLE_INFO_KEY, keys = "#roleId")
    @Override
    public SysRoleVO selectRoleById(Long roleId) {
        SysRole role = getById(roleId);
        if (role == null) {
            return null;
        }
        // 获取角色菜单列表
        List<SysRoleMenu> menus = roleMenuService.listByRoleId(roleId);
        SysRoleVO sysRoleVo = BeanUtil.copyProperties(role, SysRoleVO.class);
        return sysRoleVo.setMenuIds(CollStreamUtil.toList(menus, SysRoleMenu::getMenuId));
    }

    /**
     * 新增角色
     *
     * @param sysRoleVO 角色信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addRole(SysRoleVO sysRoleVO) {
        // 校验菜单名称是否唯一
        checkRoleNameCodeUnique(sysRoleVO);
        // 设置账户基础信息
        sysRoleVO.setStatus(RoleStatusEnum.NORMAL.getCode());
        // 插入数据库
        this.save(sysRoleVO);
        // 更新角色菜单关联关系
        roleMenuService.updateRoleMenu(sysRoleVO.getId(), sysRoleVO.getMenuIds());
    }

    /**
     * 编辑角色
     *
     * @param sysRoleVO 角色信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateRole(SysRoleVO sysRoleVO) {
        SysRole dbRole = getById(sysRoleVO.getId());
        AssertUtils.notNull(dbRole,"角色不存在");
        // 超级管理员不允许修改
        if (Objects.equals(dbRole.getCode(), UserConstants.SUPPER_ADMIN_ROLE_CODE)) {
            throw new ServiceException("无法编辑该角色");
        }
        // 校验菜单名称是否唯一
        checkRoleNameCodeUnique(sysRoleVO);
        // 更新数据库
        this.updateById(sysRoleVO);
        // 更新角色菜单关联关系
        roleMenuService.updateRoleMenu(sysRoleVO.getId(),sysRoleVO.getMenuIds());
    }

    /**
     * 校验角色名称或角色码是否唯一
     *
     * @param role 角色信息
     */
    private void checkRoleNameCodeUnique(SysRole role) {
        boolean nameExists = lambdaQuery().ne(ObjectUtil.isNotNull(role.getId()), SysRole::getId, role.getId())
                .eq(SysRole::getName, role.getName()).exists();
        if (nameExists) {
            throw new ServiceException("角色名[{}] 已存在", role.getName());
        }
        boolean codeExists = lambdaQuery().ne(ObjectUtil.isNotNull(role.getId()), SysRole::getId, role.getId())
                .eq(SysRole::getCode, role.getCode()).exists();
        if (codeExists) {
            throw new ServiceException("角色码[{}]已存在", role.getCode());
        }
    }

    /**
     * 删除角色信息
     *
     * @param roleId 角色ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteRoleById(Long roleId) {
        // 1.校验能否删除该角色
        SysRole dbRole = getById(roleId);
        AssertUtils.notNull(dbRole,"角色不存在");
        if (Objects.equals(dbRole.getCode(), UserConstants.SUPPER_ADMIN_ROLE_CODE)) {
            throw new ServiceException("无法删除该角色");
        }
        // 2.移除角色
        this.removeById(roleId);
        // 3.移除角色绑定的菜单
        roleMenuService.updateRoleMenu(dbRole.getId(), null);
    }
}

